package com.onelap.bls.tc.utils;

import android.app.Activity;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.content.LocalBroadcastManager;

import com.blankj.utilcode.util.ActivityUtils;
import com.blankj.utilcode.util.AppUtils;
import com.blankj.utilcode.util.LogUtils;
import com.blankj.utilcode.util.ServiceUtils;
import com.blankj.utilcode.util.ToastUtils;
import com.onelap.bls.tc.config.Constant;

import java.io.UnsupportedEncodingException;
import java.util.UUID;

import static android.content.Context.BIND_AUTO_CREATE;
import static com.onelap.bls.tc.utils.BLeUtil.Params.ACTION_DATA_AVAILABLE;
import static com.onelap.bls.tc.utils.BLeUtil.Params.ACTION_GATT_SERVICES_DISCOVERED;
import static com.onelap.bls.tc.utils.BLeUtil.Params.EXTRA_DATA;


public class BLeUtil {

    public static class Params {
        public final static String ACTION_GATT_CONNECTED = AppUtils.getAppPackageName() + ".ACTION_GATT_CONNECTED";
        public final static String ACTION_GATT_DISCONNECTED = AppUtils.getAppPackageName() + ".ACTION_GATT_DISCONNECTED";
        public final static String ACTION_GATT_SERVICES_DISCOVERED = AppUtils.getAppPackageName() + ".ACTION_GATT_SERVICES_DISCOVERED";
        public final static String ACTION_DATA_AVAILABLE = AppUtils.getAppPackageName() + ".ACTION_DATA_AVAILABLE";
        public final static String EXTRA_DATA = AppUtils.getAppPackageName() + ".EXTRA_DATA";
        public final static String DEVICE_DOES_NOT_SUPPORT_UART = AppUtils.getAppPackageName() + ".DEVICE_DOES_NOT_SUPPORT_UART";

        public static final String EXTRA_BATTERY_LEVEL = AppUtils.getAppPackageName() + ".EXTRA_BATTERY_LEVEL";
        public static final String BROADCAST_BATTERY_LEVEL = AppUtils.getAppPackageName() + ".BROADCAST_BATTERY_LEVEL";


        public final static String ACTION_DATA_BATTERY = AppUtils.getAppPackageName() + ".ACTION_DATA_BATTERY";

        public static final UUID TX_POWER_UUID = UUID.fromString("00001804-0000-1000-8000-00805f9b34fb");
        public static final UUID TX_POWER_LEVEL_UUID = UUID.fromString("00002a07-0000-1000-8000-00805f9b34fb");
        public static final UUID CCCD = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
        public static final UUID FIRMWARE_REVISON_UUID = UUID.fromString("00002a26-0000-1000-8000-00805f9b34fb");
        public static final UUID DIS_UUID = UUID.fromString("0000180a-0000-1000-8000-00805f9b34fb");
        public static final UUID RX_SERVICE_UUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
        public static final UUID RX_CHAR_UUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
        public static final UUID TX_CHAR_UUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");
    }


    public static final int STATUS_SEARCH_START = 100;     // Callback状态——开始搜索设备
    public static final int STATUS_SEARCH_PLAYING = 200;   //Callback状态——正在搜索设备
    public static final int STATUS_SEARCH_STOP = 200;     //Callback状态——结束搜索设备
    public static final int STATUS_DEVICE_FIND = 300;     //Callback状态——搜索到设备
    public static final int STATUS_SERVICE_CONNECTED = 400;   ////Callback状态——服务连接
    public static final int STATUS_SERVICE_DISCONNECTED = 500;   ////Callback状态——服务失去连接
    public static final int STATUS_ACTION_GATT_SERVICES_DISCOVERED = 600;   //Callback状态——连接服务后发现服务
    public static final int STATUS_ACTION_DATA_AVAILABLE = 700;   //Callback状态——连接服务后接收数据

    private BLeUtil bLeUtil;
    private BleUtilCallback bleUtilCallback;


    public BLeUtil(BleUtilCallback bleUtilCallback) {
        bLeUtil = this;
        this.bleUtilCallback = bleUtilCallback;
    }

    /**
     * 判断是否含有蓝牙模块
     *
     * @return has
     */
    public boolean judgeBluetooth() {
        Activity topActivity = ActivityUtils.getTopActivity();
        if (topActivity == null)
            return false;
        LogUtils.i("111111");
        return topActivity.getApplication().getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
    }

    /**
     * 打开蓝牙
     */
    public void openBluetooth() {
        Activity topActivity = ActivityUtils.getTopActivity();
        if (topActivity == null)
            return;
        Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
        topActivity.startActivityForResult(enableIntent, Constant.REQUEST_INTENT_ENABLE_BLUETOOTH);
    }

    /**
     * 搜索设备
     *
     * @param bluetoothAdapter bluetoothAdapter
     * @param search           是否搜索
     */
    public void searchBLeDevice(final BluetoothAdapter bluetoothAdapter, Boolean search) {
        if (search) {
            bleUtilCallback.onBleUtilCallback(STATUS_SEARCH_START, null, 0, null, null, null);
            bluetoothAdapter.startLeScan(leScanCallback);
            new Handler().postDelayed(new Runnable() {
                @Override
                public void run() {
                    bLeUtil.searchBLeDevice(bluetoothAdapter, false);
                }
            }, 10000);
        } else {
            bleUtilCallback.onBleUtilCallback(STATUS_SEARCH_STOP, null, 0, null, null, null);
            bluetoothAdapter.stopLeScan(leScanCallback);
        }
    }

    /**
     * 绑定蓝牙服务
     *
     * @param clazz 蓝牙服务
     */
    public void bindBleService(Context context, Class<? extends Service> clazz, String... intentActions) {
        ServiceUtils.bindService(clazz, serviceConnection, BIND_AUTO_CREATE);
        LocalBroadcastManager.getInstance(context).registerReceiver(broadcastReceiver, makeGattUpdateIntentFilter(intentActions));
    }

    /**
     * 解绑蓝牙服务
     */
    public void unBindBleService(Context context) {
        ServiceUtils.unbindService(serviceConnection);
        LocalBroadcastManager.getInstance(context).unregisterReceiver(broadcastReceiver);
    }


    private static IntentFilter makeGattUpdateIntentFilter(String... intentActions) {
        IntentFilter intentFilter = new IntentFilter();
        for (String s : intentActions) {
            intentFilter.addAction(s);
        }
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        return intentFilter;
    }

    private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            bleUtilCallback.onBleUtilCallback(STATUS_DEVICE_FIND, device, rssi, scanRecord, null, null);
        }
    };

    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (action != null && action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                ToastUtils.showLong("1111111111");
            }
            if (action != null && action.equals(ACTION_GATT_SERVICES_DISCOVERED)) {
                bleUtilCallback.onBleUtilCallback(STATUS_ACTION_GATT_SERVICES_DISCOVERED, null, 0, null, null, null);
            }
            if (action != null && action.equals(ACTION_DATA_AVAILABLE)) {
                byte[] txValue = intent.getByteArrayExtra(EXTRA_DATA);
                String text = null;
                try {
                    text = new String(txValue, "UTF-8");
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                LogUtils.i("ACTION_DATA_AVAILABLE", text);
                bleUtilCallback.onBleUtilCallback(STATUS_ACTION_DATA_AVAILABLE, null, 0, null, null, intent);

            }
            if (action != null && action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                int rawLevel = intent.getIntExtra("level", -1);
                int scale = intent.getIntExtra("scale", -1);
                int status = intent.getIntExtra("status", -1);
                int health = intent.getIntExtra("health", -1);
                LogUtils.i("[HomeReceiver]rawLevel:" + rawLevel + ",scale:"
                        + scale + ",status:" + status + ",health:" + health);
            }
//            if (action != null && action.equals(BROADCAST_BATTERY_LEVEL)) {
//                final int value = intent.getIntExtra(EXTRA_BATTERY_LEVEL, -1);
//                if (value > 0)
//                    onBatteryValueReceived(bluetoothDevice, value);
//            }
        }
    };

    private ServiceConnection serviceConnection = new ServiceConnection() {
        public void onServiceConnected(ComponentName className, IBinder rawBinder) {
            LogUtils.i("onServiceConnected", className);
            bleUtilCallback.onBleUtilCallback(STATUS_SERVICE_CONNECTED, null, 0, null, rawBinder, null);
        }

        public void onServiceDisconnected(ComponentName classname) {
            LogUtils.i("onServiceDisconnected", classname);
            bleUtilCallback.onBleUtilCallback(STATUS_SERVICE_DISCONNECTED, null, 0, null, null, null);
        }
    };


    /**
     * BLeUtil工具类统一回调接口
     */
    public interface BleUtilCallback {
        void onBleUtilCallback(int status, BluetoothDevice device, int rssi, byte[] scanRecord, IBinder rawBinder, Intent intent);
    }


}
